package cn.edu.zut.soft.graduate.userCenter.bo;

import cn.edu.zut.soft.basic.core.model.bo.CommonResult;
import cn.edu.zut.soft.basic.core.model.dao.Criteria;
import cn.edu.zut.soft.basic.core.model.dao.Example;
import cn.edu.zut.soft.graduate.base.bo.BasicBOImpl;
import cn.edu.zut.soft.graduate.base.dao.BasicDAO;
import cn.edu.zut.soft.graduate.base.former.InfoIdentityTransformer;
import cn.edu.zut.soft.graduate.core.constant.InfoType;
import cn.edu.zut.soft.graduate.core.constant.InfoTypeAble;
import cn.edu.zut.soft.graduate.core.constant.Role;
import cn.edu.zut.soft.graduate.core.constant.config.IKEY;
import cn.edu.zut.soft.graduate.core.design.*;
import cn.edu.zut.soft.graduate.core.model.Impl.Identity;
import cn.edu.zut.soft.graduate.core.model.Impl.Info;
import cn.edu.zut.soft.graduate.core.query.IdentityQuery;
import cn.edu.zut.soft.graduate.core.query.InfoQuery;
import cn.edu.zut.soft.graduate.core.vo.TeacherVO;
import cn.edu.zut.soft.graduate.core.vo.Witness;
import cn.edu.zut.soft.graduate.userCenter.dao.InfoDAO;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;

/**
 * Created by chuchuang on 16/10/22.
 */
@Repository
public class InfoBOImpl extends BasicBOImpl<Info, InfoQuery> implements InfoBO {
    @Resource
    private InfoDAO<Info> infoDAO;

    @Resource
    private IdentityBO identityBO;

    @Autowired
    private InfoIdentityTransformer infoIdentityTransformer;

    @Override
    protected BasicDAO<Integer, Info> getDAO() {
        return infoDAO;
    }

    @Override
    protected List<Criteria> Query(InfoQuery infoQuery) {
        Criteria criteria = new Criteria();
        if (infoQuery.getInfoType() != null){
            criteria.andEqualTo("`type`",infoQuery.getInfoType());
        }
        if (infoQuery.getKey() != null){
            criteria.andEqualTo("`key`",infoQuery.getKey());
        }
        if (infoQuery.getValue() != null){
            criteria.andEqualTo("`value`",infoQuery.getValue());
        }
        if (CollectionUtils.isNotEmpty(infoQuery.getValueList())){
            criteria.andIn("`value`",infoQuery.getValueList());
        }
        if (infoQuery.getRole() != null){
            criteria.andEqualTo("`identity_role`",infoQuery.getRole());
        }
        if (infoQuery.getIdentityId() != null){
            criteria.andEqualTo("identity_id",infoQuery.getIdentityId());
        }
        if (infoQuery.getDel() != null){
            criteria.andEqualTo("del",infoQuery.getDel());
        }else {
            criteria.andEqualTo("del", IKEY.ZERO);
        }
        return Collections.singletonList(criteria);
    }

    @Override
    public List<Info> queryByUser(final Integer id) {
        Example example = new Example();
        example.createCriteria().andEqualTo("identity_id", id).andEqualTo("del",IKEY.ZERO);
        return infoDAO.selectByExample(example);
    }

    @Override
    public boolean getExpertById(Integer userId) {
        if (userId == null){
            return false;
        }
        Example example = new Example();
        example.createCriteria().andEqualTo("`key`","witness").andEqualTo("identity_id", userId);
        List<Info> list = infoDAO.selectByExample(example);
        return !CollectionUtils.isEmpty(list);
    }


    @Override
    public List<Info> queryByUserInfoStrategy(Integer id, List<InfoStrategy> infoStrategyList) {
        Example example = new Example();
        if (infoStrategyList.isEmpty()){
            return Collections.emptyList();
        }
        for (InfoStrategy infoStrategy : infoStrategyList) {
            example.or().andEqualTo("`type`", infoStrategy.getType()).andEqualTo("`key`", infoStrategy.getKey()).andEqualTo("identity_id", id).andEqualTo("del",IKEY.ZERO);
        }
        return infoDAO.selectByExample(example);
    }

    @Override
    public List<Info> queryByInfoStrategy(List<InfoStrategy> infoStrategyList) {
        Assert.notEmpty(infoStrategyList);
        Criteria criteria = new Criteria();
        Set<InfoTypeAble> infoTypeSet = new HashSet<>();
        Set<String> keySet = new HashSet<>();
        Set<String> valueSet = new HashSet<>();
        for (InfoStrategy infoStrategy : infoStrategyList){
            infoTypeSet.add(infoStrategy.getType());
            if (infoStrategy.getKey() != null){
                keySet.add(infoStrategy.getKey());
            }
            if (infoStrategy.getValue() != null) {
                valueSet.add(infoStrategy.getValue());
            }
        }
        criteria.andIn("`type`",new ArrayList<>(infoTypeSet)).andEqualTo("del",IKEY.ZERO);
        if (CollectionUtils.isNotEmpty(keySet)){
            criteria.andIn("`key`",new ArrayList<>(keySet));
        }
        if (CollectionUtils.isNotEmpty(valueSet)){
            criteria.andIn("`value`",new ArrayList<>(valueSet));
        }
        Example example = new Example();
        example.or(criteria);
        return getDAO().selectByExample(example);
    }

    @Override
    public CommonResult<Info> save(Info info, String operator) {
        if (null == info.getParentId()) {
            info.setParentId(0);
        }
        return super.save(info, operator);
    }

    @Override
    @Transactional
    public Info save(InfoStrategy infoStrategy,Integer id, String operator) {
        Identity identity = identityBO.get(id);
        Assert.notNull(identity, "编号错误,请重新输入");
        Example example = new Example();
        example.createCriteria().andEqualTo("`key`", infoStrategy.getKey())
                .andEqualTo("identity_id", id)
                .andEqualTo("del", 0);
        List<Info> resultList = getDAO().selectByExample(example);
        CommonResult<Info> result;
        if (!resultList.isEmpty()) {
            Assert.isTrue(resultList.size() == 1, "保存重复,请重新保存");
            resultList.get(0).setValue(infoStrategy.getValue());
            result = this.update(resultList.get(0), operator);
        } else {
            Info info = new Info();
//            info.setOwner(JSONObject.toJSONString(new Owner(identity.getId(), identity.getName(), identity.getRole().name())));
            info.setKey(infoStrategy.getKey());
            info.setValue(infoStrategy.getValue());
            info.setType(infoStrategy.getType().name());
            info.setIdentityId(identity.getId());
            info.setIdentityRole(identity.getRole());
            info.setIdentityName(identity.getName());
            result = this.save(info, operator);
        }
        Assert.notNull(result);
        Assert.isTrue(result.isSuccess());
        return result.getData();
    }

    @Override
    public CommonResult saveBatch(InfoStrategy infoStrategy, Set<Integer> ids, String operator) {
        if (CollectionUtils.isEmpty(ids)) {
            return CommonResult.errorReturn("ids is null");
        }
        for (Integer id : ids){
            try {
                this.save(infoStrategy, id, operator);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return CommonResult.successReturn(true);
    }

    @Override
    public int delete(InfoStrategy infoStrategy, String opterator) {
        Example example = new Example();
        Criteria criteria = example.createCriteria();
        criteria.andEqualTo("`type`",infoStrategy.getType()).andEqualTo("`key`",infoStrategy.getType());
        return infoDAO.deleteByExample(example);
    }

    @Override
    public List<Info> delete(InfoStrategy infoStrategy, Integer id, String opterator) {
        Identity identity = identityBO.get(id);
        Assert.notNull(identity, "编号错误,请重新输入");
        List<Info> infoList = queryByUserInfoStrategy(id,Collections.singletonList(infoStrategy));
        for (Info info : infoList){
            getDAO().deleteByPrimaryKey(info.getId(),opterator);
        }
        return infoList;
    }


    @Override
    public CommonResult<List<Witness>> getAllWitness(InfoStrategy infoStrategy) {
        final InfoMassage infoMassage = InfoMassage.getInstantiate(infoStrategy);
        Example example = new Example();
        example.cleanPage()
                .createCriteria()
                .andEqualTo("type", infoMassage.getType())
                .andEqualTo("`key`", infoMassage.getKey())
                .andEqualTo("del", 0);
        List<Info> infoList = getDAO().selectByExample(example);
        List<Witness> witnessList = new ArrayList<>();
        if(CollectionUtils.isEmpty(infoList)){
            return CommonResult.successReturn(witnessList);
        }
        for (Info info : infoList) {
            try {
                witnessList.add(new Witness(info.getIdentityId(),info.getIdentityName()));
            } catch (Exception e) {
                logger.error("owner -> witness error");
            }
        }
        return CommonResult.successReturn(witnessList);
    }

    /**
     * 检索 非专家身份的 所有 教师
     * KEY = Witenss
     * 检索所有的 专家 教师
     * 去身份表 检索 非 专家的 教师
     * 根据专家 获取 List 还需要的信息什么
     *
     * @param
     * @return
     */

    @Override
    public CommonResult<List<TeacherVO>> notWitenssTeaMessage() {
        List<TeacherVO> resultTea = new ArrayList<>();
        List<Info> resultInfo = new ArrayList<>();
        CommonResult<List<Witness>> witness = this.getAllWitness(new WitnessStrategy());
        if (witness.isSuccess()) {
            CommonResult<List<Integer>> ids = identityBO.notWitnessTea(witness.getData());
            if (ids.isSuccess())
                for (Integer id : ids.getData()) {
                    Example example = new Example();
                    example.createCriteria().andEqualTo("`key`", "professionalLever").andEqualTo("identity_id", id);
                    List<Info> infoList = infoDAO.selectByExample(example);
                    resultInfo.addAll(infoList);
                }
        }
        for (Info info : resultInfo) {
            TeacherVO teacherVO = new TeacherVO();
            teacherVO.setId(info.getIdentityId().toString());
            teacherVO.setName(info.getIdentityName());
            teacherVO.setJobTitle((String) ProfessionalLever.getMap().get(info.getValue()));
            resultTea.add(teacherVO);
        }
        return CommonResult.successReturn(resultTea);
    }

    @Override
    public List<Info> selectExampleWithBLOB(InfoQuery infoQuery) {
        List<Criteria> criteriaList = Query(infoQuery);
        Example example = Example.createOfPage(infoQuery);
        for (Criteria c : criteriaList){
            example.or(c);
        }
        return infoDAO.selectByExample(example);
    }

    @Override
    public int syncTeaIdToTeaName() {
        List<Info> infoList  = queryByInfoStrategy(Collections.<InfoStrategy>singletonList(new BasicInfoStrategy(InfoType.Tea,IKEY.Guide,null)));
        Map<Integer,Info> teaIdMap = new HashMap<>();
        for (Info info:infoList){
            teaIdMap.put(info.getIdentityId(),info);
        }

        List<Info> teaName = queryByInfoStrategy(Collections.<InfoStrategy>singletonList(new BasicInfoStrategy(InfoType.Tea,IKEY.GuideName,null)));
        for (Info info:teaName){
            teaIdMap.remove(info.getIdentityId());
        }
        IdentityQuery identityQuery = new IdentityQuery();
        identityQuery.clear();
        identityQuery.setRole(Role.tea);
        List<Identity> teaList = identityBO.findByQuery(identityQuery).getData();
        Map<Integer,Identity> teaMap = new HashMap<>(teaList.size());
        for (Identity identity:teaList){
            teaMap.put(identity.getId(),identity);
        }

        for (Map.Entry<Integer,Info> me : teaIdMap.entrySet()){
            Info info = me.getValue();
            info.setId(null);
            info.setKey(IKEY.GuideName);
            info.setValue(teaMap.get(Integer.parseInt(me.getValue().getValue())).getName());
//            afterSave();
            //不是用aftersave
            getDAO().insert(me.getValue());
        }
        return teaIdMap.size();
    }

    @Override
    public List<Info> getInfo(String key, Integer id) {
        List<Info> result = Lists.newArrayList();
        if(StringUtils.isEmpty(key) || id == null){
            return result;
        }
        Example example = new Example();
        example.createCriteria().andEqualTo("`key`", key).andEqualTo("del", "0").andEqualTo("identity_id", id);
        result = infoDAO.selectByExample(example);
        return result;
    }

}
